import axios from 'axios';
import type { AxiosInstance, AxiosResponse, InternalAxiosRequestConfig, AxiosError } from 'axios';
import { message } from 'antd';
import type {
    CreateRequestConfig,
    RequestInterceptors,
    RequestOptions,
    ResponseData
} from './types';
import { typeGuards } from './types';

/**
 * 封装响应结果，提供便捷访问方法
 */
export class HttpResponse<T> {
    private readonly rawResponse: ResponseData<T>;

    constructor(response: ResponseData<T>) {
        this.rawResponse = response;
    }

    /**
     * 获取原始响应
     */
    get raw(): ResponseData<T> {
        return this.rawResponse;
    }

    /**
     * 获取响应码
     */
    get code(): number {
        return this.rawResponse.code;
    }

    /**
     * 获取响应消息
     */
    get message(): string {
        return this.rawResponse.message;
    }

    /**
     * 获取单个数据对象
     * 如果是列表，返回第一个元素；如果是空响应，返回null
     */
    get data(): T | null {
        if (typeGuards.isEmptyResponse(this.rawResponse)) {
            return null;
        }
        if (typeGuards.isListResponse(this.rawResponse)) {
            return this.rawResponse.data.length > 0 ? this.rawResponse.data[0] : null;
        }
        return this.rawResponse.data;
    }

    /**
     * 获取数据列表
     * 如果是单个对象，返回包含该对象的数组；如果是空响应，返回空数组
     */
    get list(): T[] {
        if (typeGuards.isEmptyResponse(this.rawResponse)) {
            return [];
        }
        if (typeGuards.isListResponse(this.rawResponse)) {
            return this.rawResponse.data;
        }
        return [this.rawResponse.data];
    }

    /**
     * 获取分页元数据
     * 如果没有分页信息，返回null
     */
    get meta() {
        return typeGuards.isListResponse(this.rawResponse) ? this.rawResponse.meta : null;
    }

    /**
     * 响应是否为空
     */
    get isEmpty(): boolean {
        return typeGuards.isEmptyResponse(this.rawResponse);
    }

    /**
     * 响应是否为列表
     */
    get isList(): boolean {
        return typeGuards.isListResponse(this.rawResponse);
    }

    /**
     * 响应是否为单个对象
     */
    get isSingle(): boolean {
        return typeGuards.isSingleResponse(this.rawResponse);
    }

    /**
     * 操作是否成功
     */
    get isSuccess(): boolean {
        return this.rawResponse.code === 0;
    }

    /**
     * 列表长度
     * 如果不是列表，返回0或1
     */
    get length(): number {
        if (typeGuards.isEmptyResponse(this.rawResponse)) {
            return 0;
        }
        if (typeGuards.isListResponse(this.rawResponse)) {
            return this.rawResponse.data.length;
        }
        return 1; // 单个对象
    }

    /**
     * 处理成功响应，执行回调
     * @param callback 成功时执行的回调函数
     * @returns this，支持链式调用
     */
    onSuccess(callback: (data: T | T[] | null) => void): this {
        if (this.isSuccess) {
            if (this.isList) {
                callback(this.list);
            } else if (this.isSingle) {
                callback(this.data);
            } else {
                callback(null);
            }
        }
        return this;
    }

    /**
     * 处理失败响应，执行回调
     * @param callback 失败时执行的回调函数
     * @returns this，支持链式调用
     */
    onError(callback: (code: number, message: string) => void): this {
        if (!this.isSuccess) {
            callback(this.code, this.message);
        }
        return this;
    }

    /**
     * 对列表数据进行映射转换
     * @param mapFn 映射函数
     * @returns 映射后的数组
     */
    mapList<R>(mapFn: (item: T, index: number) => R): R[] {
        return this.list.map(mapFn);
    }

    /**
     * 过滤列表数据
     * @param filterFn 过滤函数
     * @returns 过滤后的数组
     */
    filterList(filterFn: (item: T, index: number) => boolean): T[] {
        return this.list.filter(filterFn);
    }
}

export class Request<T = unknown> {
    private instance: AxiosInstance;
    private interceptors?: RequestInterceptors<T>;
    private defaultOptions: RequestOptions = {
        showLoading: true,
        showError: true,
    };

    constructor(config: CreateRequestConfig<T>) {
        this.instance = axios.create(config);
        this.interceptors = config.interceptors;
        this.setupInterceptors();
    }

    private setupInterceptors() {
        // 默认请求拦截器
        this.instance.interceptors.request.use(
            (config: InternalAxiosRequestConfig) => {
                const token = localStorage.getItem('access_token');
                if (token) {
                    const tokenType = localStorage.getItem('token_type') || 'Bearer';
                    config.headers.Authorization = `${tokenType} ${token}`;
                }
                return config;
            },
            (error: AxiosError) => {
                return Promise.reject(error);
            }
        );

        // 默认响应拦截器
        this.instance.interceptors.response.use(
            (response: AxiosResponse<ResponseData<unknown>>) => {
                const { data } = response;
                if (data.code === 401) {
                    message.error('登录已过期，请重新登录');
                    localStorage.removeItem('access_token');
                    localStorage.removeItem('token_type');
                    setTimeout(() => {
                        window.location.href = '/login';
                    }, 1500);
                    return Promise.reject(data);
                }

                if (data.code !== 0) {
                    message.error(data.message);
                    return Promise.reject(data);
                }
                return response;
            },
            (error: AxiosError) => {
                if (error.response) {
                    const { status } = error.response;
                    switch (status) {
                        case 401:
                            message.error('登录已过期，请重新登录');
                            localStorage.removeItem('access_token');
                            localStorage.removeItem('token_type');
                            setTimeout(() => {
                                window.location.href = '/login';
                            }, 1500);
                            break;
                        case 403:
                            message.error('拒绝访问');
                            break;
                        case 404:
                            message.error('请求地址不存在');
                            break;
                        case 500:
                            message.error('服务器错误');
                            break;
                        default:
                            message.error('网络错误');
                    }
                } else if (error.request) {
                    message.error('网络请求超时');
                } else {
                    message.error('请求配置错误');
                }
                return Promise.reject(error);
            }
        );

        // 自定义请求拦截器
        if (this.interceptors?.requestInterceptor) {
            this.instance.interceptors.request.use(
                this.interceptors.requestInterceptor as unknown as (
                    config: InternalAxiosRequestConfig
                ) => InternalAxiosRequestConfig | Promise<InternalAxiosRequestConfig>,
                this.interceptors.requestInterceptorCatch
            );
        }

        // 自定义响应拦截器
        if (this.interceptors?.responseInterceptor) {
            this.instance.interceptors.response.use(
                this.interceptors.responseInterceptor,
                this.interceptors.responseInterceptorCatch
            );
        }
    }

    /**
     * 发送HTTP请求
     * 返回封装的响应对象，提供便捷访问方法
     */
    public async request<D>(config: CreateRequestConfig<D>): Promise<HttpResponse<D>> {
        const { requestOptions, ...axiosConfig } = config;
        const options: RequestOptions = { ...this.defaultOptions, ...requestOptions };

        try {
            const response = await this.instance.request<ResponseData<D>>(axiosConfig);
            // 返回封装的响应对象
            return new HttpResponse<D>(response.data);
        } catch (error) {
            if (options.onError && error instanceof Error) {
                options.onError(error);
            }
            return Promise.reject(error);
        }
    }

    /**
     * GET请求
     */
    public get<D>(
        url: string,
        params?: Record<string, unknown>,
        config?: Omit<CreateRequestConfig<D>, 'method' | 'url' | 'params'>
    ): Promise<HttpResponse<D>> {
        return this.request<D>({ ...config, method: 'GET', url, params });
    }

    /**
     * POST请求
     */
    public post<D>(
        url: string,
        data?: Record<string, unknown>,
        config?: Omit<CreateRequestConfig<D>, 'method' | 'url' | 'data'>
    ): Promise<HttpResponse<D>> {
        return this.request<D>({ ...config, method: 'POST', url, data });
    }

    /**
     * PUT请求
     */
    public put<D>(
        url: string,
        data?: Record<string, unknown>,
        config?: Omit<CreateRequestConfig<D>, 'method' | 'url' | 'data'>
    ): Promise<HttpResponse<D>> {
        return this.request<D>({ ...config, method: 'PUT', url, data });
    }

    /**
     * DELETE请求
     */
    public delete<D>(
        url: string,
        config?: Omit<CreateRequestConfig<D>, 'method' | 'url'>
    ): Promise<HttpResponse<D>> {
        return this.request<D>({ ...config, method: 'DELETE', url });
    }
} 